﻿
namespace Vboot.Core.Module.Sys;

public class SysOrgRoleNodeService : BaseCateService<SysOrgRoleNode>, ITransient
{
    
    public async Task Insertx(SysOrgRoleNode node)
    {
        //处理层级信息
        if (string.IsNullOrEmpty(node.id))
        {
            node.id = YitIdHelper.NextId() + ""; 
        }
        if (node.parent != null)
        {
            node.pid = node.parent.id;
            var parentTier = await repo.Context.Queryable<SysOrgRoleNode>()
                .Where(it => it.id == node.pid).Select(it => it.tier).SingleAsync();
            node.tier = parentTier + node.id + "x";
        }
        else
        {
            node.tier = "x" + node.id + "x";
        }
        await base.InsertAsync(node);
    }

    public async Task Updatex(SysOrgRoleNode node)
    {
        //处理上级部门与部门层级信息
        if (node.parent != null)
        {
            node.pid = node.parent.id;
            var parentTier = await repo.Context.Queryable<SysOrgRoleNode>()
                .Where(it => it.id == node.pid).Select(it => it.tier).SingleAsync();
            node.tier = parentTier + node.id + "x";
            var arr = parentTier.Split("x");
            if (arr.Any(str => node.id == str))
            {
                throw new Exception("父节点不能为自己或者自己的子节点");
            }
        }
        else
        {
            node.tier = "x" + node.id + "x";
        }

        var olderTier = await repo.Context.Queryable<SysOrgRoleNode>()
            .Where(it => it.id == node.id).Select(it => it.tier).SingleAsync();
        //事务包裹处理数据库操作
        repo.Context.Ado.BeginTran();
        await base.UpdateAsync(node);
        await DealNodeTier(olderTier, node.tier, node.id);
        repo.Context.Ado.CommitTran();
    }

    private async Task DealNodeTier(string oldTier, string newTier, string id)
    {
        var idNameList = await
            repo.Context.Ado.SqlQueryAsync<ZidName>(
                "select id,tier as name from sys_org_role_node where tier like @oldTier and id<>@id",
                new {id, oldTier = oldTier + "%"});

        var dtList = new List<Dictionary<string, object>>();
        foreach (var idName in idNameList)
        {
            var dt = new Dictionary<string, object>
            {
                {"id", idName.id}, {"tier", idName.name.Replace(oldTier, newTier)}
            };
            dtList.Add(dt);
        }

        await repo.Context.Updateable(dtList).AS("sys_org_role_node").WhereColumns("id").ExecuteCommandAsync();
    }
    
    public async Task Move(TreeMovePo po)
    {
        var dragNode = await SingleAsync(po.draid);
        List<SysOrgRoleNode> list2 = await repo.Context.Queryable<SysOrgRoleNode>()
            .Where(it => it.ornum > dragNode.ornum)
            .Where(it => it.pid == dragNode.pid)
            .ToListAsync();
        foreach (var cate in list2)
        {
            cate.ornum--;
            await UpdateOrnumAsync(cate);
        }
        
        if (po.type == "inner")
        {
            dragNode.pid = po.droid;
            int count = await repo.Context.Queryable<SysOrgRoleNode>()
                .Where(t => t.pid == po.droid)
                .Where(t => t.treid == dragNode.treid)
                .CountAsync();
            dragNode.ornum = count + 1;
        }
        else if (po.type == "before")
        {
            var dropNode = await SingleAsync(po.droid);
            dragNode.pid = dropNode.pid;
            dragNode.ornum = dropNode.ornum;
            List<SysOrgRoleNode> list = await repo.Context.Queryable<SysOrgRoleNode>()
                .Where(it => it.ornum > dropNode.ornum)
                .Where(t => t.treid == dragNode.treid)
                .Where(it => it.pid == dropNode.pid)
                .ToListAsync();
            foreach (var cate in list)
            {
                cate.ornum++;
                await UpdateOrnumAsync(cate);
            }
            dropNode.ornum++;
            await UpdateOrnumAsync(dropNode);
        }
        else if (po.type == "after")
        {
            var dropNode = await SingleAsync(po.droid);
            int count = await repo.Context.Queryable<SysOrgRoleNode>()
                .Where(t => t.pid == dropNode.pid)
                .Where(t => t.treid == dragNode.treid)
                .CountAsync();
            if (dragNode.pid == dropNode.pid)
            {
                dragNode.ornum = count;
            }
            else
            {
                dragNode.pid = dropNode.pid;
                dragNode.ornum = count + 1;
            }
        }
        await UpdateAsync(dragNode);
    }
    
    private async Task UpdateOrnumAsync(SysOrgRoleNode node)
    {
        await repo.Context.Updateable<SysOrgRoleNode>()
            .SetColumns(it => it.ornum == node.ornum)
            .Where(it => it.id == node.id)
            .ExecuteCommandAsync();
    }
    
    public SysOrgRoleNodeService(SqlSugarRepository<SysOrgRoleNode> repo)
    {
        this.repo = repo;
    }
}